#ifndef BASE_SHORT_HAND_H
#define BASE_SHORT_HAND_H

#include <iostream>

/*******************************************************************************
** Vector Shorthand
*******************************************************************************/
typedef Vector<float,2> Vector2f;
typedef Vector<float,3> Vector3f;
typedef Vector<float,4> Vector4f;

template< typename T >
  Vector<T,2> NewVector( T x, T y ) {
    T array [] = { x, y };
    Vector<T,2> temp( array );
    return temp;
  }

template< typename T >
  Vector<T,3> NewVector( T x, T y, T z ) {
    T array [] = { x, y, z };
    Vector<T,3> temp( array );
    return temp;
  }

template< typename T >
  Vector<T,4> NewVector( T x, T y, T z, T w ) {
    T array [] = { x, y, z, w };
    Vector<T,4> temp( array );
    return temp;
  }

/*******************************************************************************
** Matrix Shorthand
*******************************************************************************/
typedef Matrix<float,2,2> Matrix2f;
typedef Matrix<float,3,3> Matrix3f;
typedef Matrix<float,4,4> Matrix4f;

template< typename T >
  Matrix<T,2,2> NewMatrix( T ax, T bx,
                           T ay, T by ) {
    T array [] = { ax, bx,
                   ay, by };
    Matrix<T,2,2> temp( array );
    return temp;
  }

template< typename T >
  Matrix<T,3,3> NewMatrix( T ax, T bx, T cx,
                           T ay, T by, T cy,
                           T az, T bz, T cz ) {
    T array [] = { ax, bx, cx,
                   ay, by, cy,
                   az, bz, cz };
    Matrix<T,3,3> temp( array );
    return temp;
  }

template< typename T >
  Matrix<T,4,4> NewMatrix( T ax, T bx, T cx, T dx,
                           T ay, T by, T cy, T dy,
                           T az, T bz, T cz, T dz,
                           T aw, T bw, T cw, T dw ) {
    T array [] = { ax, bx, cx, dx,
                   ay, by, cy, dy,
                   az, bz, cz, dz,
                   aw, bw, cw, dw };
    Matrix<T,4,4> temp( array );
    return temp;
  }

template< typename T >
Matrix<T,3,3> RotateX( T angle ) {
  T val[] = { 1, 0,           0,
              0, cos(angle),  sin(angle),
              0, -sin(angle), cos(angle) };
  return Matrix<float,3,3>( val );
}

template< typename T >
Matrix<T,3,3> RotateY( T angle ) {
  T val[] = { cos(angle), 0, -sin(angle),
              0,          1, 0,
              sin(angle), 0, cos(angle) };
  return Matrix<float,3,3>( val );
}

template< typename T >
Matrix<T,3,3> RotateZ( T angle ) {
  T val[] = { cos(angle),  sin(angle), 0,
              -sin(angle), cos(angle), 0,
              0,           0,          1  };
  return Matrix<float,3,3>( val );
}

template< typename T >
Matrix<T,4,4> RotateX4( T angle ) {
  T val[] = { 1, 0,           0,          0,
              0, cos(angle),  sin(angle), 0,
              0, -sin(angle), cos(angle), 0,
              0, 0,           0,          1 };
  return Matrix<float,4,4>( val );
}

template< typename T >
Matrix<T,4,4> RotateY4( T angle ) {
  T val[] = { cos(angle), 0, -sin(angle), 0,
              0,          1, 0,           0,
              sin(angle), 0, cos(angle),  0,
              0,          0, 0,           1 };
  return Matrix<float,4,4>( val );
}

template< typename T >
Matrix<T,4,4> RotateZ4( T angle ) {
  T val[] = { cos(angle),  sin(angle), 0, 0,
              -sin(angle), cos(angle), 0, 0,
              0,           0,          1, 0,
              0,           0,          0, 1 };
  return Matrix<float,4,4>( val );
}


/*******************************************************************************
** Print Functions
*******************************************************************************/
template< typename T, unsigned int N >
void PrintVector( const Vector<T,N> vector ) {
  std::cout << "Vector: ";
  for( unsigned int j = 0; j < N; ++j ) {
    std::cout << vector[j] << " ";
  }
  std::cout << std::endl << std::endl;
}

template< typename T, unsigned int N, unsigned int M >
void PrintMatrix( const Matrix<T,N,M> matrix, bool coloum_vector ) {
  std::cout << "Matrix: " << "Coloums: " << N << " " << "Rows: " << M;

  if( coloum_vector ) {
    for( unsigned int j = 0; j < M; ++j ) {
      std::cout << std::endl << "  ";
      for( unsigned int k = 0; k < N; ++k ) {
        std::cout << matrix[k][j] << " ";
      }
    }
  }
  else {
    for( unsigned int j = 0; j < N; ++j ) {
      std::cout << std::endl << "  ";
      for( unsigned int k = 0; k < M; ++k ) {
        std::cout << matrix[j][k] << " ";
      }
    }
  }

  std::cout << std::endl << std::endl;
}

#endif
